package com.songlanyun.modules.withdraw.service.impl;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.songlanyun.common.enums.*;
import com.songlanyun.common.exception.RRException;
import com.songlanyun.common.utils.BeanUtil;
import com.songlanyun.common.utils.OrderGen;
import com.songlanyun.common.utils.PageUtils;
import com.songlanyun.common.utils.Query;
import com.songlanyun.common.utils.custom.MathUtils;
import com.songlanyun.modules.account.dao.AccountDao;
import com.songlanyun.modules.account.entity.AccountEntity;
import com.songlanyun.modules.account.entity.UserThirdIdentityEntity;
import com.songlanyun.modules.account.model.vo.AccountInfoVO;
import com.songlanyun.modules.account.service.AccountService;
import com.songlanyun.modules.account.service.UserIdentityAssetService;
import com.songlanyun.modules.account.service.UserThirdIdentityService;
import com.songlanyun.modules.distributionconfig.entity.DistributionConfig;
import com.songlanyun.modules.distributionconfig.service.DistributionConfigService;
import com.songlanyun.modules.exception.BillException;
import com.songlanyun.modules.exception.MemberException;
import com.songlanyun.modules.exception.ShopException;
import com.songlanyun.modules.gains.service.ShopGainsBillService;
import com.songlanyun.modules.gains.service.ShopOrderGainsService;
import com.songlanyun.modules.integralrecord.entity.IntegralRecord;
import com.songlanyun.modules.integralrecord.service.IntegralRecordService;
import com.songlanyun.modules.memberbill.service.SaleRefillCardBillService;
import com.songlanyun.modules.pointsexchangeconfig.entity.PointsExchangeConfigEntity;
import com.songlanyun.modules.pointsexchangeconfig.service.PointsExchangeConfigService;
import com.songlanyun.modules.shop.entity.ShopEntity;
import com.songlanyun.modules.shop.model.vo.GetShopWithdrawVO;
import com.songlanyun.modules.shop.model.vo.ShopWithdrawVO;
import com.songlanyun.modules.shop.service.ShopService;
import com.songlanyun.modules.sysbill.service.SysBillService;
import com.songlanyun.modules.userbankcard.entity.UserBankCardEntity;
import com.songlanyun.modules.userbankcard.service.UserBankCardService;
import com.songlanyun.modules.usergains.service.UserBillService;
import com.songlanyun.modules.usergains.service.UserOrderGainsService;
import com.songlanyun.modules.withdraw.dao.WithdrawDao;
import com.songlanyun.modules.withdraw.entity.Withdraw;
import com.songlanyun.modules.withdraw.model.dto.CommissionToBalanceDTO;
import com.songlanyun.modules.withdraw.model.dto.ShopWithdrawDTO;
import com.songlanyun.modules.withdraw.model.dto.UserWithdrawDTO;
import com.songlanyun.modules.withdraw.model.dto.WithdrawDTO;
import com.songlanyun.modules.withdraw.model.vo.AccountWalletVO;
import com.songlanyun.modules.withdraw.service.WithdrawService;
import com.songlanyun.pay.bean.WithdrawBean;
import com.songlanyun.pay.common.api.ApiResult;
import com.songlanyun.pay.service.PayService;
import org.apache.commons.lang.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;


@Service("yxtSaleWithdrawService")
public class WithdrawServiceImpl extends ServiceImpl<WithdrawDao, Withdraw> implements WithdrawService {


    @Resource
    private AccountService accountService;

    @Resource
    private ShopService shopService;

    @Resource
    private SysBillService sysBillService;

    @Resource
    private ShopGainsBillService shopGainsBillService;

    @Resource
    private UserBillService userBillService;

    @Resource
    private UserIdentityAssetService userIdentityAssetService;

    @Resource
    private ShopOrderGainsService shopOrderGainsService;

    @Resource
    private DistributionConfigService distributionConfigService;

    @Resource
    private SaleRefillCardBillService saleRefillCardBillService;

    @Resource
    private RedissonClient redissonClient;

    @Resource
    private PointsExchangeConfigService pointsExchangeConfigService;

    @Resource
    private IntegralRecordService integralRecordService;

    @Resource
    private UserThirdIdentityService userThirdIdentityService;

    @Resource
    private AccountDao accountDao;

    @Resource
    private UserBankCardService userBankCardService;

    @Resource
    @Qualifier("payService2")
    private PayService payService;


    @Resource
    private UserOrderGainsService userOrderGainsService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        Integer withdrawType = MapUtil.getInt(params, "withdraw_type");//提现类型
        Integer paymentTerm = MapUtil.getInt(params, "payment_term");// 收款方式
        Integer verifyStatus = MapUtil.getInt(params, "verify_status");//审核状态
        Integer remitStatus = MapUtil.getInt(params, "remit_status");//打款状态
        Integer userType = MapUtil.getInt(params, "user_type");//用户类型
        Long identityId = MapUtil.getLong(params, "identity_id");//用户Id

        String businessCode = MapUtil.getStr(params, "business_code");//业务单号
        String thirdPayCode = MapUtil.getStr(params, "thirdPay_code");//流水号

        IPage<Withdraw> page = this.page(
                new Query<Withdraw>().getPage(params),
                new LambdaQueryWrapper<Withdraw>()
                        .eq(withdrawType != null, Withdraw::getWithdrawType, withdrawType)
                        .eq(paymentTerm != null, Withdraw::getPaymentTerm, paymentTerm)
                        .eq(verifyStatus != null, Withdraw::getVerifyStatus, verifyStatus)
                        .eq(remitStatus != null, Withdraw::getRemitStatus, remitStatus)
                        .eq(userType != null, Withdraw::getUserType, userType)
                        .eq(identityId != null, Withdraw::getIdentityId, identityId)

                        .like(StringUtils.isNotBlank(businessCode), Withdraw::getBusinessCode, businessCode)
                        .like(StringUtils.isNotBlank(thirdPayCode), Withdraw::getThirdPayCode, thirdPayCode)
                        .orderByDesc(Withdraw::getCreateTime)

        );

        return new PageUtils(page);
    }

    @Override
    public List<Withdraw> exportList(Map<String, Object> params) {
        String businessCode = MapUtil.getStr(params, "business_code");//业务单号
        Integer verifyStatus = MapUtil.getInt(params, "verify_status");//审核状态
        return this.baseMapper.selectList(
                new LambdaQueryWrapper<Withdraw>()
                        .eq(verifyStatus != null, Withdraw::getVerifyStatus, verifyStatus)
                        .like(StringUtils.isNotBlank(businessCode), Withdraw::getBusinessCode, businessCode)
                        .orderByDesc(Withdraw::getCreateTime)

        );
    }

    @Override
    public PageUtils memberPage(Map<String, Object> params) {
        Long userId = MapUtil.getLong(params, "user_id");//用户Id
        IPage<Withdraw> page = this.page(
                new Query<Withdraw>().getPage(params),
                new LambdaQueryWrapper<Withdraw>()
                        .eq(Withdraw::getUserType, WithdrawConstant.UserType.MEMBER)
                        .eq(Withdraw::getIdentityId, userId)
                        .orderByDesc(Withdraw::getCreateTime)
        );

        return new PageUtils(page);
    }

    @Override
    public List<Withdraw> memberList(Long userId) {
        return this.list(
                new LambdaQueryWrapper<Withdraw>()
                        .eq(Withdraw::getUserType, WithdrawConstant.UserType.MEMBER)
                        .eq(Withdraw::getIdentityId, userId)
                        .orderByDesc(Withdraw::getCreateTime)
        );

    }


    /**
     * 初始化创建
     *
     * @param withdrawType 提现类型
     * @param userType     用户身份
     * @param paymentTerm  收款方式
     * @param identityId   身份id
     * @return
     */
    @Override
    public Withdraw init(WithdrawConstant.WithdrawType withdrawType, WithdrawConstant.UserType userType, Integer paymentTerm, Long identityId) {
        Withdraw withdraw = new Withdraw();

        withdraw.setWithdrawType(withdrawType);//提现类型
        withdraw.setBusinessCode("T" + OrderGen.generateOrderNo());//提现单号
        withdraw.setVerifyStatus(WithdrawConstant.VerifyStatus.VERIFY_WAIT.getCode());//待审核
        withdraw.setPaymentTerm(paymentTerm);
        withdraw.setUserType(userType);//用户身份
        withdraw.setIdentityId(identityId);//身份id
        withdraw.setRemitStatus(false);//打款状态
        return withdraw;
    }

    /**
     * 会员分佣提现
     *
     * @param dto
     * @param userId
     */
    @Override
    public void memberWithdraw(UserWithdrawDTO dto, Long userId) {
        //校验金额有没有超过商家当前提现上限
        this.verifyUserWithdrawUp(userId, dto.getMoney());

        //初始化创建
        Withdraw withdraw = this.init(WithdrawConstant.WithdrawType.MEMBER_WITHDRAW, WithdrawConstant.UserType.MEMBER, dto.getPaymentTerm(), userId);
        //查询服务积分兑换比例

        withdraw.setMoney(dto.getMoney());


        AccountInfoVO accountInfoVO = accountDao.getAllById(withdraw.getIdentityId());
        withdraw.setUserMobile(accountInfoVO.getMobile());//会员手机号
        withdraw.setPayee(ObjectUtil.isNotNull(accountInfoVO.getRealName()) ? accountInfoVO.getRealName() : accountInfoVO.getNickname());//收款人
        withdraw.setWithdrawMobile(accountInfoVO.getMobile());//提现手机号

        switch (dto.getPaymentTerm()) {
            case 0://微信
                //查询用户是否绑定微信
                userThirdIdentityService.loadByThirdType(userId, MemberConstant.ThirdType.WECHAT, true);
                withdraw.setWithdrawAccount(WithdrawConstant.PaymentTerm.getMsgByCode(withdraw.getPaymentTerm()));
                break;
            case 1://支付宝
                //查询用户是否绑定支付宝
                userThirdIdentityService.loadByThirdType(userId, MemberConstant.ThirdType.ALIPAY, true);
                withdraw.setWithdrawAccount(WithdrawConstant.PaymentTerm.getMsgByCode(withdraw.getPaymentTerm()));
                break;
            case 2://银行
                if (true) {
                    //TODO
                    throw new RRException("未对接银行卡服务,敬请期待！！！");
                }
                //只有服务体系成员用户才可使用银行卡提现
                AccountEntity accountEntity = accountService.getUserById(userId, true);
//                if (accountEntity.getServiceSystemProvince().getCode().equals(GoodsConstant.ServicePackageArea.NOT.getCode())) {
//                    throw new RRException(MemberException.ONLY_MEMBERS_OF_THE_SERVICE_SYSTEM_CAN_USE_BANK_CARDS_TO_WITHDRAW_CASH);
//                }
                //查询银行卡
                UserBankCardEntity bankCard = userBankCardService.loadById(userId, dto.getUserBankId(), true);
                withdraw.setBankName(bankCard.getBankName());
                withdraw.setWithdrawAccount(bankCard.loadDesCardNum());
                break;
            case 4://公益积分
                withdraw.setWithdrawAccount(WithdrawConstant.PaymentTerm.getMsgByCode(withdraw.getPaymentTerm()));
                break;
            default:
                break;
        }

        //保存提现记录
        this.save(withdraw);
    }

    /**
     * 商家所得提现
     *
     * @param dto
     * @param shopId
     */
    @Override
    public void shopWithdraw(ShopWithdrawDTO dto, Long shopId) {

        //校验金额有没有超过商家当前提现上限
        this.verifyShopWithdrawUp(shopId, dto.getMoney());

        //初始化创建
        Withdraw withdraw = this.init(WithdrawConstant.WithdrawType.SHOP_WITHDRAW, WithdrawConstant.UserType.SHOP, dto.getPaymentTerm(), shopId);

        BeanUtil.copyPropertiesIgnoreNull(dto, withdraw);

        ShopEntity shopEntity = shopService.loadShopBy(shopId, true);

        BigDecimal commissionCost = MathUtils.setScale(withdraw.getMoney().doubleValue() * shopEntity.getCommissionRate().doubleValue() / 100);
        withdraw.setMoney(MathUtils.subtract(withdraw.getMoney(),commissionCost));
        withdraw.setCommissionCost(commissionCost);
        //查询商家名称
        withdraw.setShopName(shopEntity.getShopName());//商家名称
        this.save(withdraw);
    }



    @Override
    public GetShopWithdrawVO getShopWithdraw(ShopWithdrawDTO dto, Long shopId) {
        //校验金额有没有超过商家当前提现上限
        this.verifyShopWithdrawUp(shopId, dto.getMoney());
        ShopEntity shopEntity = shopService.loadShopBy(shopId, true);
        BigDecimal commissionCost = MathUtils.setScale(dto.getMoney().doubleValue() * shopEntity.getCommissionRate().doubleValue() / 100);
        GetShopWithdrawVO vo = new GetShopWithdrawVO();
        vo.setMoney(dto.getMoney());
        vo.setCommissionCost(commissionCost);
        vo.setFactMoney(MathUtils.subtract(dto.getMoney(),commissionCost));
        return null;
    }

    @Override
    public Withdraw getById(Long id, boolean isThrow) {
        Withdraw withdraw = this.getById(id);

        if (withdraw == null) {
            if (isThrow) {
                throw new RRException(BillException.WITHDRAW_RECORD_NOT_EXIST);
            }
        }

        return withdraw;
    }

    /**
     * 校验会员分佣提现金额有没有超过会员当前提现上限
     *
     * @param money 提现服务积分
     */
    @Override
    public void verifyUserWithdrawUp(Long userId, BigDecimal money) {
        //校验提现上下限
        verifyMoneyBound(money);

        //会员可提现金额
        BigDecimal commissionAble = userIdentityAssetService.getCommissionAble(userId);
        //查询该会员的所有锁定总金额（未打款、未失败的金额）
        BigDecimal sum = this.baseMapper.getSumByShopLockAmount(WithdrawConstant.UserType.MEMBER, userId);

        //比较金额
        //可提现金额 - 待审核提现总金额 >= 提现金额
        if (MathUtils.subtract(commissionAble, sum).compareTo(money) < 0) {
            throw new RRException(MemberException.MEMBER_WITHDRAW_INSUFFICIENT_FUND);
        }

    }

    @Override
    public void verifyUserWithdrawUpForCheck(Long userId, BigDecimal money) {
        verifyMoneyBound(money);

        //会员可提现金额
        BigDecimal commissionAble = userIdentityAssetService.getCommissionAble(userId);
        //查询该会员的所有锁定总金额（未打款、未失败的金额）
        BigDecimal sum = this.baseMapper.getSumByShopLockAmount(WithdrawConstant.UserType.MEMBER, userId);

        //比较金额
        //可提现金额 - 待审核提现总金额 >= 提现金额
        if (MathUtils.subtract(commissionAble, sum).compareTo(BigDecimal.ZERO) < 0) {
            throw new RRException(MemberException.MEMBER_WITHDRAW_INSUFFICIENT_FUND);
        }
    }

    /**
     * 校验商家可提现金额有没有超过商家当前提现上限
     *
     * @param money 提现金额
     */
    @Override
    public void verifyShopWithdrawUp(Long shopId, BigDecimal money) {
        //校验提现上下限
        verifyMoneyBound(money);

        //商家可提现金额
        BigDecimal gainsAble = shopService.getGainsAble(shopId);
        //查询该商家的所有锁定总金额（未打款、未失败的金额）
        BigDecimal sum = this.baseMapper.getSumByShopLockAmount(WithdrawConstant.UserType.SHOP, shopId);

        //比较金额
        //商家可提现金额 - 待审核提现总金额 >= 提现金额
        if (MathUtils.subtract(gainsAble, sum).compareTo(money) < 0) {
            throw new RRException(ShopException.SHOP_WITHDRAW_INSUFFICIENT_FUND);
        }

    }

    @Override
    public void verifyShopWithdrawUpForCheck(Long shopId, BigDecimal money) {
        //校验提现上下限
        verifyMoneyBound(money);

        //商家可提现金额
        BigDecimal gainsAble = shopService.getGainsAble(shopId);
        //查询该商家的所有锁定总金额（未打款、未失败的金额）
        BigDecimal sum = this.baseMapper.getSumByShopLockAmount(WithdrawConstant.UserType.SHOP, shopId);

        //比较金额
        //商家可提现金额 - 待审核提现总金额 >= 提现金额
        if (MathUtils.subtract(gainsAble, sum).compareTo(BigDecimal.ZERO) < 0) {
            throw new RRException(ShopException.SHOP_WITHDRAW_INSUFFICIENT_FUND);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void withdrawCheck(WithdrawDTO dto) {
        //查询提现
        Withdraw withdraw = this.getById(dto.getId(), true);
        if (!WithdrawConstant.VerifyStatus.VERIFY_WAIT.getCode().equals(withdraw.getVerifyStatus())) {
            throw new RRException(BillException.THE_WITHDRAWAL_IS_NOT_PENDING);
        }

        //审核成功后 校验下金额
        if (WithdrawConstant.VerifyStatus.VERIFY_PASS.getCode().equals(dto.getVerifyStatus())) {
            switch (withdraw.getWithdrawType()) {
                case SHOP_WITHDRAW:
                    //校验金额有没有超过商家当前提现上限
                    this.verifyShopWithdrawUpForCheck(withdraw.getIdentityId(), withdraw.getMoney());
                    break;
                case MEMBER_WITHDRAW:
                    //校验金额有没有超过用户当前提现上限
                    this.verifyUserWithdrawUpForCheck(withdraw.getIdentityId(), withdraw.getMoney());
                    break;
                default:
                    return;
            }
        }

        //更新提现审核状态
        withdraw.setVerifyMan(dto.getVerifyMan());//审核人
        withdraw.setVerifyStatus(dto.getVerifyStatus());//审核状态
        withdraw.setVerifyOpinion(dto.getVerifyOpinion());//理由
        withdraw.setVerifyRemark(dto.getVerifyRemark());//备注
        withdraw.setVerifyTime(new Date());//审核时间
        this.updateById(withdraw);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void remit(WithdrawDTO dto) {
        //查询该提现记录
        Withdraw withdraw = this.getById(dto.getId(), true);
        if (!withdraw.getVerifyStatus().equals(WithdrawConstant.VerifyStatus.VERIFY_PASS.getCode())) {
            //审核通过才能打款
            throw new RRException(BillException.VERIFY_PASS);
        }

        switch (withdraw.getWithdrawType()) {
            case SHOP_WITHDRAW:
                //商家提现打款
                this.shopWithdrawRemit(withdraw, dto);
                break;
            case MEMBER_WITHDRAW:
                //用户提现打款
                this.memberWithdrawRemit(withdraw, dto);
                break;
            default:
                return;
        }

        //处理提现逻辑
        this.affirmWithdraw(withdraw);

    }

    private void shopWithdrawRemit(Withdraw withdraw, WithdrawDTO dto) {
        //校验金额有没有超过用户当前提现上限
        this.verifyShopWithdrawUp(withdraw.getIdentityId(), withdraw.getMoney());

        //修改提现记录
        withdraw.setThirdPayCode(dto.getThirdPayCode());//交易单号
        withdraw.setBankName(dto.getBankName());
        withdraw.setRemitMan(dto.getRemitMan());
        withdraw.setRemitTime(dto.getRemitTime());

        this.updateById(withdraw);
    }

    private void memberWithdrawRemit(Withdraw withdraw, WithdrawDTO dto) {
        //校验金额有没有超过用户当前提现上限
        this.verifyUserWithdrawUp(withdraw.getIdentityId(), withdraw.getMoney());
        withdraw.setRemitMan(dto.getRemitMan());//打款人
        withdraw.setRemitTime(new Date());

        //提现
        switch (withdraw.getPaymentTerm()) {
            case 0://微信
                //查询用户是否绑定微信

                UserThirdIdentityEntity wechat = userThirdIdentityService.loadByThirdType(withdraw.getIdentityId(), MemberConstant.ThirdType.WECHAT, true);
                ApiResult wechatWithdrawResult = this.withdraw(withdraw.getMoney(), wechat.getIdentityCode(), withdraw.getBusinessCode(), WithdrawConstant.WithdrawThirdType.WITHDRAW_MONEY_TO_WECHAT);
                if (wechatWithdrawResult.getCode() != 200) {
                    throw new RRException(String.format("微信兑换失败 [%s]", wechatWithdrawResult.getMsg()));
                }
                Map<String, String> wechatResult = (Map<String, String>) wechatWithdrawResult.getData();

//                withdraw.setThirdPayCode(wechatResult.get("batch_id"));//交易单号
                withdraw.setThirdPayCode(wechatResult.get("payment_no"));//微信付款单号
                break;

            case 1://支付宝
                //查询用户是否绑定支付宝

                //查询用户是否绑定支付宝
                UserThirdIdentityEntity alipay = userThirdIdentityService.loadByThirdType(withdraw.getIdentityId(), MemberConstant.ThirdType.ALIPAY, true);
                ApiResult alipayWithdrawResult = this.withdraw(withdraw.getMoney(), alipay.getIdentityCode(), withdraw.getBusinessCode(), WithdrawConstant.WithdrawThirdType.WITHDRAW_TO_PAY_ALIPAY);
                if (alipayWithdrawResult.getCode() != 200) {
                    throw new RRException(String.format("支付宝兑换失败 [%s]", alipayWithdrawResult.getMsg()));
                }
                Map<String, String> alipayResult = (Map<String, String>) alipayWithdrawResult.getData();

                withdraw.setThirdPayCode(alipayResult.get("orderId"));//交易单号

                break;
            case 2://银行卡
                throw new RRException("未对接银行卡服务,敬请期待！！！");
//                    break;
            case 4://公益积分
                //提现成功
                //保存公益积分记录
//                integralRecordService.inner(new IntegralRecord(withdraw.getIdentityId(), withdraw.getMoney(),
//                        IntegralConstant.InnerMode.SERVICE_POINTS_WITHDRAW_TO_WELFARE_INTEGRAL, IntegralConstant.IntegralModelType.SERVICE_POINTS_WITHDRAW_TO_WELFARE_INTEGRAL,
//                        withdraw.getId(), "服务积分提现到公益积分"));

//                withdraw.setThirdPayCode("FT" + OrderGen.generateOrderNo());//交易单号
                break;
            default:
                break;
        }
    }

    /**
     * 确认提现
     */
    private void affirmWithdraw(Withdraw withdraw) {
        //修改提现记录
        withdraw.setRemitStatus(true);//已打款
        this.updateById(withdraw);

        switch (withdraw.getWithdrawType()) {
            case SHOP_WITHDRAW:
                //商家所得提现
                shopGainsBillService.outBill(withdraw.getIdentityId(), ShopGainsConstant.OuterMode.DRAW_MONEY, withdraw.getMoney(),
                        String.format("商家所得兑换金额：%s，兑换单号：%s", withdraw.getMoney(), withdraw.getBusinessCode()), withdraw.getBusinessCode());
                break;
            case MEMBER_WITHDRAW:
                //会员分佣提现
                userBillService.outBill(withdraw.getIdentityId(), String.format("会员兑换：%s，兑换单号：%s", withdraw.getMoney(), withdraw.getBusinessCode()),
                        UserBillConstant.OuterMode.WITHDRAW, withdraw.getMoney(), withdraw.getBusinessCode(),"系统");
                break;
            default:
                return;
        }

        //查询账单类型
        BillConstant.BillType billType = typeCastType(withdraw.getWithdrawType());
        //查询支付方式
        WithdrawConstant.PaymentTerm byCode = WithdrawConstant.PaymentTerm.getByCode(withdraw.getPaymentTerm());
        OrderConstant.PayMode payMode = typeCastMode(byCode);
        //生成平台账单
        sysBillService.saveExpenditureBill(
                payMode, billType, withdraw.getMoney(), withdraw.getBusinessCode(), withdraw.getThirdPayCode(),
                withdraw.getPayee(), withdraw.getWithdrawAccount(), withdraw.getWithdrawMobile(),
                withdraw.getShopName(), withdraw.getBankName(), withdraw.getUserMobile()
        );
    }

    @Override
    public AccountWalletVO getWalletInfo(Long userId) {
        AccountWalletVO vo = this.baseMapper.getWalletInfo(userId);
        if (vo != null) {
            //冻结金额
            BigDecimal sum = this.baseMapper.getSumByShopLockAmount(WithdrawConstant.UserType.MEMBER, userId);
            vo.setFreezing(sum);
            //设置新的可提现佣金（减去了冻结中的金额）
            vo.setCommissionAble(MathUtils.subtractMulti(vo.getCommissionAble(), sum));

            vo.setWaitAccount(userOrderGainsService.loadByWaitAccount(userId));

        }

        return vo;
    }


    @Override
    public ShopWithdrawVO statistics(Long shopId) {
        ShopWithdrawVO vo = shopService.getWithdrawAmount(shopId);
        if (vo != null) {
            //设置冻结中的金额
            //冻结金额
            BigDecimal sum = this.baseMapper.getSumByShopLockAmount(WithdrawConstant.UserType.SHOP, shopId);
            vo.setLockAmount(sum);
            //设置可提现金额（减去冻结中的金额）
            vo.setGainsAble(MathUtils.subtractMulti(vo.getGainsAble(), sum));
            //设置已结算所得
            vo.setWithdrawAmount(shopOrderGainsService.waitInBill(shopId));
        }
        return vo;
    }


    /**
     * 提现类型转账单类型
     *
     * @param withdrawType
     * @return
     */
    private BillConstant.BillType typeCastType(WithdrawConstant.WithdrawType withdrawType) {
        BillConstant.BillType billType = null;
        switch (withdrawType) {
            case SHOP_WITHDRAW:
                billType = BillConstant.BillType.SHOP_WITHDRAW;//商家所得提现
                break;
            case MEMBER_WITHDRAW:
                billType = BillConstant.BillType.MEMBER_WITHDRAW;//会员分佣金提现
                break;
        }

        return billType;
    }

    /**
     * 付款方式转支付类型
     *
     * @param paymentTerm
     * @return
     */
    private OrderConstant.PayMode typeCastMode(WithdrawConstant.PaymentTerm paymentTerm) {
        OrderConstant.PayMode payMode = null;
        switch (paymentTerm) {
            case WE_CHAT:
                payMode = OrderConstant.PayMode.WE_CHAT;//微信
                break;
            case ALIPAY:
                payMode = OrderConstant.PayMode.ALIPAY;//支付宝
                break;
            case BANK:
                payMode = OrderConstant.PayMode.BANK;//银行卡
                break;
            case READY_UP:
                payMode = OrderConstant.PayMode.READY_UP;//现金
                break;
            case WELFARE_INTEGRAL:
                payMode = OrderConstant.PayMode.WELFARE_INTEGRAL;//公益积分
                break;
        }

        return payMode;
    }

    /**
     * 检验金额上下限
     */
    private void verifyMoneyBound(BigDecimal money) {
        DistributionConfig config = distributionConfigService.getConfig();
        if (config != null) {
            //下限//上限
            if (money.compareTo(config.getMinExtract()) < 0) {
                throw new RRException("兑换额度不得低于" + config.getMinExtract());
            }

            if (money.compareTo(config.getMaxExtract()) > 0) {
                throw new RRException("兑换额度不得高于" + config.getMaxExtract());
            }
        }
    }

    /**
     * 佣金转存余额
     *
     * @param userId
     * @param dto
     */
    @Transactional
    @Override
    public void commissionToBalance(Long userId, CommissionToBalanceDTO dto) {
        RLock lock = redissonClient.getLock(LockPrefixConstant.USER_ASSET_BIG + userId);
        lock.lock(2, TimeUnit.SECONDS);
        try {
            //校验金额有没有超过商家当前提现上限
            this.verifyUserWithdrawUp(userId, dto.getMoney());
            //会员分佣所得减少
            userBillService.outBill(userId, String.format("会员佣金转存余额,金额：%s元", dto.getMoney()),
                    UserBillConstant.OuterMode.COMMISSION_TO_BALANCE, dto.getMoney(), "","会员自己");

            //余额增加
            saleRefillCardBillService.addBalance(userId, dto.getMoney(), "",
                    BillConstant.InnerMode.COMMISSION_TO_BALANCE);
        } finally {
            lock.unlock();
        }

    }

    @Override
    public Integer count(Long userId) {
        return this.lambdaQuery()
                .eq(Withdraw::getUserType, WithdrawConstant.UserType.MEMBER)
                .eq(Withdraw::getIdentityId, userId)
                .eq(Withdraw::getVerifyStatus, 1)
                .eq(Withdraw::getRemitStatus, true)
                .count();
    }

    @Override
    public ApiResult withdraw(BigDecimal amount, String identity, String outBizNo, WithdrawConstant.WithdrawThirdType withdrawType) {
        WithdrawBean withdrawBean = new WithdrawBean();
        withdrawBean.setAmount(amount);
        withdrawBean.setWithdrawType(withdrawType.getCode());
        withdrawBean.setIdentity(identity);
        withdrawBean.setOutBizNo(outBizNo);
        try {
            return payService.entPay(withdrawBean);
        } catch (Exception e) {
            throw new RRException("兑换失败");
        }
    }


}
